詳解Terraform第3版 3章〜4章
https://gyazo.com/f7bec0609a1a743fbb4ca5e3e0e50472
3章 Terraform State
Terraformプロジェクトのファイルレイアウトや分離、ロックなど
stateファイルをなぜgit管理しないのか-> 手動管理・ロックできない・シークレットが含まれる
S3ほかクラウドストレージ、Terraform Cloud などで解決できる
DynamoDB使ったロック
まずはstate管理用のバケット作成をTerraformで
S3関連リソース
bucket
lifecycle は Terraform 向けの記述と理解
BucketAlreadyExists になってわからんになってたがバケット名はユニークである必要がある
bucket versioning enabled
bucket server-side encryption
2023.1からデフォルトで暗号化されるようになったので書かなくてデフォルトで暗号化はされる
bucket access control
ACLとかはあまり理解できていないが、現時点ではレガシー機能なはず
ロック用DynamoDB
terraform ブロックを作成しその後 terraform init
output ブロックを作成してS3 tfstateばバージョニングされていることを確認
制限
tfstate 向けのリソースを作成後にinitして、リソースを削除してからローカルtfstateにするためinitという順番になるので注意が必要
terraform backend に変数は使えない (つまりヒューマンエラーやオペミスが起きやすい
backend.hcl といったファイルを作成して -backend-config オプションに渡せるとあるが実用性があるのかよくわからない
tfstateの分離
https://gyazo.com/1268660c08851db0fe0cd980801a7928
手法としては2つ
Terraform ワークスペース
通常はtfstateを作成してdefaultワークスペースが一つあるのみ
terraform workspace new exmaple1 で追加・スイッチ
サブコマンドは delete, new, list, select, show
ワークスペース追加時点でバケットに新しいtfstateが生える
問題点
すべて同じバケットにtfstateが存在するためアクセス権(パスごとにポリシーを変更できるとしても)が同じになる
つまりステージングと本番環境の分離に向いていない
CLIで現在どのworkspaceを選択中かわからない
それあを踏まえると問題を引き起こしかねない
ファイルレイアウト
各環境のTerraformファイルは別のフォルダとして独立させ、環境ごとに違うバックエンド(違うアカウント、認証情報)でアクセス権を変更する
細かいコンポーネントレベルでも分離、デプロイライフサイクルでも分離できる
書籍では環境(stg/prod)、環境ごとのコンポーネントレベルでわけることを推奨
code:exmaple-layout.txt
{stg,prod}/
- vpc/
- service/
- frontend-app/
- backend-app/
- variables.tf
- outputs.tf
- main.tf
- data-storage/
- redis/
- mysql/
global/
- iam/
- s3/
一方でデメリット
複数フォルダであるため一括でapplyができない
コピペが増える -> 4章モジュールが参考になる
リソース間の依存関係が難しくなる -> フォルダを別にするとリソースに対して参照ができないのでハードな文字列などで参照する必要が出てくる *.id, *.arn
terraform remote state
別のTerraformプロジェクトのtfstateから値を読み出す
AWS RDS から mysql を作成してuser/passを環境変数から読み出すようにする
e.g. export TF_VAR_db_username=foo
tkdn.icon RDS作成は時間がかかる
data "terraform_remote_state" {} で読み出しが可能になる、もちろんterraform backend s3バケットへのアクセス権は同じではないといけない
だし読み出し専用 = DBへの変更影響なしに参照が可能になる
tkdn.icon さすがに remote state まで HCL LSP では補完効かないですね
templatefile ビルトイン関数 format
実装はGo fmt.Sprintf まま?
これを使ってサーバ起動スクリプトをテンプレートファイルにする
stg/prodでコピペせずに済む方法が次章のモジュールになるというつなぎ方
4章 モジュール
これまで書いたものも設定ファイルはすべてモジュールと言える
直接applyを実行するものをルートモジュール(terraformが実行されるディレクトリ)
他のモジュールから利用できるものを再利用可能なモジュール
初手モジュール基礎
まずは3章で作成した Staging 向けの ASG, ALB, SG をモジュール化するところから
provider 定義を削除すればすぐ再利用可能なモジュール
ただしこの段階ではStaging向けの記述がハードコートされているので次節
terraform init ではプロバイダのインストールとバックエンドの設定、モジュールのダウンロードを実行する
そのままではWarningが出る
│ Warning: Backend configuration ignored
│ on ../../../modules/webserver-cluster/main.tf line 141, in terraform:
│ 141: backend "s3" {
│ Any selected backend applies to the entire configuration, so Terraform expects provider configurations only in the root module.
│ This is a warning rather than an error because it's sometimes convenient to temporarily call a root module as a child module for testing purposes, but this backend configuration block will have no effect.
│ (and one more similar warning elsewhere)
モジュール変数
modules/path/to/variables.tf に変数を定義し、ルートモジュールで使用する記法
stg/prod 別にスペックを変更したいなどの要求を満たすための変数も追加
https://gyazo.com/18bce4b489819968a3ca1104d1498a47
tkdn.icon LSがあって支援されるのは嬉しいが、同期が遅いように感じる
ローカルな値
モジュールにおけるすべてを変数化してしまうとモジュール使用者が誤って値を上書きしかねない
CIDRブロックやポート、あらゆるプロトコルを意味する-1
変数ではなくlocals {}ブロックでローカルな値を使用する
モジュール内のみでしか使用できないので他のモジュールからの影響を考慮しなくてよい
モジュール出力
モジュールにおいても output ブロックを使って値を出力することができる
ProdのASスケジュールを設定する際を例にしている
ファイルパスの注意
path.module: 定義のあるモジュールが存在するFSパス
path.root: ルートモジュールのパス
path.cwd: 現在のワーキングディレクトリパス
インラインブロックの注意
aws_security_group リソースではingress/egressのルールをインラインブロックでも別のリソース参照でも定義できる
両方を混ぜると設定がコンフリクトするため、モジュールの場合は常に別のリソースを使ったほうがよい(by筆者
ほかにもインラインブロックを定義でき問題になるリソースについては要参照
要注意コラム
Staging/Production いずれも同じVPCにリソースを作成したが本来は別にしないと、ルートテーブルの変更が大きな影響を及ぼしたり攻撃者がアクセス権を得たりするなど問題が生じる
モジュール=設計図といった説明
modules ディレクトリの変更でtagをプッシュし、適用したい環境のmoduleブロックのsourceにリポジトリのパスを指定することも可能
code:main.tf
module "webserver_cluster" {
source = "git@github.com:tkdn/terraform-up-and-running.git//ch4.modules/modules/services/webserver-cluster?ref=v0.3.0"
}
ただしGitリポジトリの認証ががある場合はTerraformにも認証情報を伝える必要がある(SSHなど
tag を更新後は必ず init してモジュールをダウンロードしておく必要がある
https://gyazo.com/fb58ca7140e668515f6ea468a784cc23
tkdn.iconだし、これ path.module 効かなくなってそもそも apply できへんやんけ
https://gyazo.com/25279687dba86e679c850dd82142c1d4
嘘、${path.module}/user_data.sh パスにスラッシュ入ってなかっただけでした